package com.bjtu.douyin.controller;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.bjtu.common.auth.AuthRedisKey;
import com.bjtu.common.pojo.UserVideo;
import com.bjtu.common.pojo.Video;
import com.bjtu.common.util.Result;
import com.bjtu.common.util.ResultCode;
import com.bjtu.douyin.mapper.UserVideoMapper;
import com.bjtu.douyin.service.FileService;
import com.bjtu.douyin.service.VideoService;
import com.bjtu.douyin.utils.video.GrpcClient;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Random;


@Api(tags = "视频增删改查")
@RestController
@RequestMapping("/video")
public class VideoController {

    @Autowired
    private VideoService videoService;

    @Autowired
    private FileService fileService;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private UserVideoMapper userVideoMapper;

    @Autowired
    private NacosServiceManager nacosServiceManager;

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @GetMapping("/hello")
    public String hello() throws NacosException {
        NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
        return namingService.getAllInstances("api-recommend").toString();
    }


    /**
     * 通过token获取用户id
     *
     * @param token 用户token
     * @return 用户id
     */
    public Integer getUserIdByToken(String token) {
        ValueOperations<Object, Object> ops = redisTemplate.opsForValue();
        return (Integer) ops.get(AuthRedisKey.TOKEN_TO_UID + token);
    }

    /**
     * 添加视频
     *
     * @param title 视频标题
     * @param file 上传的视频文件
     * @param token 请求头中的用户token
     * @return 返回处理结果信息
     */
    @PostMapping("")
    public Result<?> addVideo(@RequestParam("title") String title,
                              @RequestParam("file") MultipartFile file,
                              @RequestHeader("token") String token) {
        // 通过token获取用户id
        Integer userId = getUserIdByToken(token);
        if (userId == null) {
            return Result.error(ResultCode.FAILED, "用户未登录");
        }
        // 上传视频到OSS
        String url;
        try {
            url = fileService.uploadFile(file);
        } catch (Exception e) {
            return Result.error(ResultCode.FAILED, "服务器错误");
        }
        // 构建video对象
        Video video = new Video();
        video.setStatus(1);
        video.setLikeNumber(0);
        video.setTitle(title);
        video.setUrl(url);
        video.setUserId(userId);
        video.setCreateTime(LocalDateTime.now());
        return videoService.addVideo(video);
    }

    /**
     * 删除视频
     *
     * @param id 视频id
     * @return 返回处理结果信息
     */
    @DeleteMapping("/{id}")
    public Result<?> deleteVideo(@PathVariable Integer id,
                                 @RequestHeader("token") String token) {
        Integer userId = getUserIdByToken(token);
        if (userId == null) {
            return Result.error(ResultCode.FAILED, "用户未登录");
        }
        return videoService.deleteVideo(id);
    }

    /**
     * 通过id获取单个视频
     */
    @GetMapping("/{id}")
    public Result<?> getVideo(@PathVariable Integer id,
                              @RequestHeader(value = "token", required = false) String token) {
        Integer userId = null;
        if (token != null && !token.isEmpty()) {
            userId = getUserIdByToken(token);
            if (userId == null) {
                return Result.error(ResultCode.FAILED, "用户未登录");
            }
        }
        return videoService.getVideo(id, userId);
    }

    /**
     * 获取视频列表
     */
    @GetMapping("/list")
    public Result<?> getVideoList(
            @RequestHeader("token") String token,
            @RequestParam("pageIndex") Integer pageIndex,
            @RequestParam("pageSize") Integer pageSize) {
        // 通过token获取用户id
        Integer userId = getUserIdByToken(token);
        if (userId == null) {
            return Result.error(ResultCode.FAILED, "用户未登录");
        }
        return videoService.getVideoList(userId, pageIndex, pageSize);
    }

    @GetMapping("/get-recommend-videos")
    public Result<?> getRecommendVideos(@RequestParam("userId") int userId,@RequestParam("count") int count) throws NacosException {
        NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
        List<Instance> allInstances = namingService.getAllInstances("api-recommend");
        int numInstances = allInstances.size();
        Random random = new Random();
        int randomIndex = random.nextInt(numInstances);
        String ip = allInstances.get(randomIndex).getIp();
        int port = allInstances.get(randomIndex).getPort();
        GrpcClient grpcClient = new GrpcClient(ip,port);
        List<com.bjtu.douyin.utils.video.Video> videos;
        try {
            videos=grpcClient.sendMessage(userId,count);
        }catch (Exception e){
            return Result.error(ResultCode.FAILED,"调用微服务失败");
        }


        //添加视频id到user_video表
        for (com.bjtu.douyin.utils.video.Video video : videos) {
            Integer videoId = (Integer) video.getId();

            // 创建 UserVideo 对象
            UserVideo userVideo = new UserVideo();
            userVideo.setUserId(userId);
            userVideo.setVideoId(videoId);

            // 插入到 user_video 表中
            userVideoMapper.insert(userVideo);
        }

        //处理数据以输出
        StringBuilder jsonBuilder = new StringBuilder();
        JsonFormat.Printer printer = JsonFormat.printer();
        try {
            jsonBuilder.append("[");
            boolean first = true;
            for (Message message : videos) {
                if (!first) {
                    jsonBuilder.append(",");
                }
                jsonBuilder.append(printer.print(message));
                first = false;
            }
            jsonBuilder.append("]");
        } catch (Exception e) {
            e.printStackTrace();
        }
        String r = jsonBuilder.toString();
        JSONArray jsonArray = JSONArray.parseArray(r);
        return Result.success(jsonArray);
    }


    /**
    *  点赞视频
    * @param id 视频id
    * @return 返回处理结果信息
    */
    @PutMapping("/like")
    public Result<?> likeVideo(@RequestParam("id") Integer id, @RequestHeader("token") String token) {
        Integer userId = getUserIdByToken(token);
        if (userId == null) {
            return Result.error(ResultCode.FAILED, "用户未登录");
        }
        return videoService.likeVideo(id, userId);
    }

    /**
     *  取消点赞视频
     * @param id 视频id
     * @return 返回处理结果信息
     */
    @PutMapping("/dislike")
    public Result<?> dislikeVideo(@RequestParam("id") Integer id, @RequestHeader("token") String token) {
        Integer userId = getUserIdByToken(token);
        if (userId == null) {
            return Result.error(ResultCode.FAILED, "用户未登录");
        }
        return videoService.dislikeVideo(id, userId);
    }
}
